package com.pj.app.auraSimulator;

import java.awt.Color;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Random;

import com.pj.app.auraSimulator.listeners.OnTask;
import com.pj.app.auraSimulator.parsers.XMLParser.UserXMLModel;
import com.pj.lib.aura.connection.AuraTypeModel;

import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.awt.WorldWindowGLCanvas;
import gov.nasa.worldwind.formats.dds.Color32;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.BasicShapeAttributes;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.Offset;
import gov.nasa.worldwind.render.PointPlacemark;
import gov.nasa.worldwind.render.PointPlacemarkAttributes;
import gov.nasa.worldwind.render.SurfaceCircle;
import gov.nasa.worldwind.view.orbit.BasicOrbitView;
import gov.nasa.worldwind.view.orbit.OrbitView;

public class SimulatorWorldWindCanvas extends WorldWindowGLCanvas{
	private ArrayList<WorldWindUser> mUsers = new ArrayList<SimulatorWorldWindCanvas.WorldWindUser>();
	private ArrayList<AuraTypeModel> mAuraTypes;
	
	Random random = new Random();
	
	RenderableLayer layer;
	BasicOrbitView orbitView;
	public SimulatorWorldWindCanvas(Controller c, ArrayList<UserXMLModel> users, ArrayList<AuraTypeModel> auraTypes) {
		super();
		
		this.mAuraTypes= (ArrayList<AuraTypeModel>) auraTypes.clone();
		System.out.println("a: " + mAuraTypes.size());
		
		File dir = new File("images/");
		FilenameFilter filter = new FilenameFilter() {
		    public boolean accept(File dir, String name) {
		        return name.endsWith(".png");
		    }
		};
		String[] children = dir.list(filter);
		
		int i = 0;
		for(UserXMLModel user : users) {
			if(i >= children.length) {
				i = 0;
			}
			mUsers.add(new WorldWindUser(children[i], user.nickName));
			i++;
		}
		
		c.addOnTaskListener(new OnTask() {
			
			@Override
			public void setAura(int userId, int localId, String auraCode) {
				handleSetAura(localId, auraCode);
				SimulatorWorldWindCanvas.this.redrawNow();
			}
			
			@Override
			public void locationChanged(int userId, int localId, double[] loc) {
				handleLocationChanged(localId, loc);
				SimulatorWorldWindCanvas.this.redrawNow();
			}
			
			@Override
			public void disableAura(int userId, int localId) {
				handleDisableAura(localId);
				SimulatorWorldWindCanvas.this.redrawNow();
			}
		});
		
	}
	public void initGUI() {

		
		
		//create a layer and add Polyline
		layer = new RenderableLayer();

		
		//add layer to WorldWind
		this.getModel().getLayers().add(layer);
		
		orbitView= (BasicOrbitView) this.getView();
		
	}
	protected void handleDisableAura(int localId) {

		mUsers.get(localId- 1).disableAura();
	}
	protected void handleLocationChanged(int localId, double[] loc) {
		System.out.println(mAuraTypes.size());
		mUsers.get(localId -1).changeLoc(loc);

	}
	protected void handleSetAura(int localId, String auraCode) {
		mUsers.get(localId- 1).initAura(auraCode);
	}
	
	private AuraTypeModel getAuraTypeByCode(String auraCode) {

		for(AuraTypeModel aura: mAuraTypes) {
			System.out.println(aura.code + " = " + auraCode);
			if(aura.code.equals(auraCode)) {
				return aura;
			}
		}
		return null;
	}
	
	private class WorldWindUser {
		public WorldWindUser(String pin, String nickname) {
			this.pin = pin;
			this.nickName = nickname;
		}
		public double[] loc;
		public String pin;
		public Boolean isAuraSet = false;
		public int auraRadius;
		public String nickName;
		
		public PointPlacemark mPlacemark;
		public SurfaceCircle mAura;
		
		private Boolean placeMarkInited = false;
		private Boolean isAuraShown = false;
		
		public void initPlaceMark() {
			Position position = new Position(LatLon.fromDegrees(loc[0], loc[1]), loc[2]);
			mPlacemark = new PointPlacemark(new Position(LatLon.fromDegrees(loc[0], loc[1]), loc[2]));
			mPlacemark.setLabelText(nickName);
			mPlacemark.setLineEnabled(false);
			mPlacemark.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);
			
			PointPlacemarkAttributes attrs = new PointPlacemarkAttributes();
            attrs.setImageAddress(pin);
            attrs.setImageColor(new Color(1f, 1f, 1f, 0.6f));
            attrs.setScale(0.6);
//            attrs.setImageOffset(new Offset(19d, 8d, AVKey.PIXELS, AVKey.PIXELS));
            attrs.setLabelOffset(new Offset(0.9d, 0.6d, AVKey.FRACTION, AVKey.FRACTION));
            mPlacemark.setAttributes(attrs);
            
            orbitView.addPanToAnimator(orbitView.getCenterPosition(), 
            		position, orbitView.getHeading(), orbitView.getHeading(), orbitView.getPitch(), orbitView.getPitch(), 
            		orbitView.getZoom(), 10000, 1500, true); 
            //orbitView.addCenterAnimator(orbitView.getCenterPosition(), position, true);
            //orbitView.addFlyToZoomAnimator(orbitView.getHeading(), orbitView.getPitch(), 10000); 
    		//orbitView.setCenterPosition(position);
    		//orbitView.setZoom(10000);
		}
		
		public void initAura(String auraCode) {
			AuraTypeModel atm = getAuraTypeByCode(auraCode);
			
			mAura = new SurfaceCircle(LatLon.fromDegrees(loc[0], loc[1]), atm.radius);
			
			BasicShapeAttributes attr = new BasicShapeAttributes();
			attr.setInteriorOpacity(0.2);
			attr.setInteriorMaterial(new Material(COLORS_ARRAY[random.nextInt(COLORS_ARRAY.length)]));
			
			mAura.setAttributes(attr);
			
			layer.addRenderable(mAura);
			
			isAuraShown = true;
			
		}
		
		public void disableAura() {
			isAuraShown = false;
			layer.removeRenderable(mAura);
		}
		
		public void changeLoc(double[] loc) {
			this.loc = loc;
			if(placeMarkInited) {
				mPlacemark.setPosition(new Position(LatLon.fromDegrees(loc[0], loc[1]), loc[2]));
				
			} else {
				initPlaceMark();
				layer.addRenderable(mPlacemark);
				placeMarkInited = true;
			}
			
			if(isAuraShown) {
				mAura.setCenter(new Position(LatLon.fromDegrees(loc[0], loc[1]), loc[2]));
			}
			
		}
		
		
		
		private final Color[] COLORS_ARRAY = {Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GREEN, Color.MAGENTA, Color.RED, Color.YELLOW};
		
	}
}
